package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
	"sync/atomic"
)

type DbConfig struct {
	PortalList  []string /*ip:port的列表，如["192.168.0.12:5432", "192.168.0.13:5432"]*/
	portalIndex uint32
	User        string
	Dbname      string
	Passwd      string
}

func (cfg *DbConfig) getNextPortal() string {
	var idx uint32
	var count = uint32(len(cfg.PortalList))
	idx = atomic.AddUint32(&cfg.portalIndex, 1)
	return cfg.PortalList[idx%count]
}

func inArray(strArray []string, key string) bool {
	var item string
	for _, item = range strArray {
		if item == key {
			return true
		}
	}
	return false
}

func LoadConfig(configFile string, proxyConf map[string]string, dbsConf map[string]*DbConfig) error {

	proxyOpt := []string{"listen_port", "listen_addr", "default_pool_size", "max_client_conn"}

	confFp, err := os.Open(configFile)
	if err != nil {
		return err
	}
	defer func() { confFp.Close() }()

	buff := bufio.NewReader(confFp)

	var key string
	var val string
	var lineno int = 0
	var pdbConf *DbConfig
	var idx int
	var ok bool

	for {
		line, err := buff.ReadString('\n')
		lineno++

		if err != nil || io.EOF == err {
			break
		}

		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "#") {
			continue
		}

		if len(line) < 3 {
			continue
		}

		idx = strings.Index(line, "=")
		if len(line) <= 1 {
			continue
		}
		if idx < 0 {
			return fmt.Errorf("Invalid line(no '='): %s ", line)
		}

		key = line[0:idx]
		key = strings.TrimSpace(key)
		val = line[idx+1:]
		val = strings.TrimSpace(val)

		if inArray(proxyOpt, key) {
			proxyConf[key] = val
			continue
		}

		items := strings.Split(key, ".")
		if len(items) != 3 {
			return fmt.Errorf("Invalid item in %d line: %s", lineno, line)
		}

		if items[0] != "db" {
			return fmt.Errorf("Invalid item in %d line: %s", lineno, line)
		}

		pdbConf, ok = dbsConf[items[1]]
		if !ok { /*如果没有匹配到则添加到map中*/
			pdbConf = new(DbConfig)
			dbsConf[items[1]] = pdbConf
		}

		switch strings.ToLower(items[2]) {
		case "ipport":
			pdbConf.PortalList = strings.Split(val, ",")
		case "user":
			pdbConf.User = val
		case "dbname":
			pdbConf.Dbname = val
		case "passwd":
			pdbConf.Passwd = val
		default:
			return fmt.Errorf("Invalid item in %d line: %s", lineno, line)
		}

	}

	return nil
}
